﻿<!DOCTYPE HTML>
<html lang="zh">
<head>
<title>轻松访问收藏夹 - 脚本示例 | AutoHotkey v2</title>
<meta name="description" content="This script allows selecting a favorite folder in a menu by clicking the middle mouse button while certain types of windows are active." />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link href="../static/theme.css" rel="stylesheet" type="text/css" />
<script src="../static/content.js" type="text/javascript"></script>
</head>
<body>

<h1>轻松访问收藏夹 <span class="headnote">作者: Savage</span></h1>

<p>当您在某些类型的窗口活动时点击鼠标中键, 脚本会显示您的收藏夹菜单. 选择收藏夹中的文件夹后, 脚本会让活动窗口立即切换到那个文件夹. 支持下列窗口类型: 1) 标准的文件打开或文件保存对话框; 2) 资源管理器窗口; 3) 控制台(命令提示符) 窗口. 对于不支持的窗口类型也可以显示此菜单, 此时选择的收藏夹中的文件夹会在新的资源管理器窗口中打开.
</p>
<p><a href="FavoriteFolders.ahk">下载此脚本</a> &nbsp;| &nbsp;<a href="index.htm">其他示例脚本</a> &nbsp;| &nbsp;<a href="../AutoHotkey.htm">主页</a></p>

<pre class="NoIndent"><em>; CONFIG: CHOOSE YOUR HOTKEY
; If your mouse has more than 3 buttons, you could try using
; XButton1 (the 4th) or XButton2 (the 5th) instead of MButton.
; You could also use a modified mouse button (such as ^MButton) or
; a keyboard hotkey.  In the case of MButton, the tilde (~) prefix
; is used so that MButton's normal functionality is not lost when
; you click in other window types, such as a browser.  The presence
; of a tilde tells the script to avoid showing the menu for
; unsupported window types.  In other words, if there is no tilde,
; the hotkey will always display the menu; and upon selecting a
; favorite while an unsupported window type is active, a new
; Explorer window will be opened to display the contents of that
; folder.</em>
f_Hotkey := "~MButton"

<em>; CONFIG: CHOOSE YOUR FAVORITES
; Update the special commented section below to list your favorite
; folders.  Specify the name of the menu item first, followed by a
; semicolon, followed by the name of the actual path of the favorite.
; Use a blank line to create a separator line.</em>

<em>/*
ITEMS IN FAVORITES MENU &lt;-- Do not change this string.
Desktop      ; %USERPROFILE%\Desktop
Favorites    ; %USERPROFILE%\Favorites
Documents    ; %USERPROFILE%\Documents

Program Files; %PROGRAMFILES%
*/</em>


<em>; END OF CONFIGURATION SECTION
; Do not make changes below this point unless you want to change
; the basic functionality of the script.</em>

#SingleInstance  <em>; Needed since the hotkey is dynamically created.</em>

Hotkey f_Hotkey, "f_DisplayMenu"
if SubStr(f_Hotkey, 1, 1) = "~"  <em>; Show menu only for certain window types.</em>
    f_AlwaysShowMenu := false
else
    f_AlwaysShowMenu := true

<em>; Used to reliably determine whether script is compiled:</em>
SplitPath A_ScriptName,,, f_FileExt
if f_FileExt = "Exe"  <em>; Read the menu items from an external file.</em>
    f_FavoritesFile := A_ScriptDir "\Favorites.ini"
else  <em>; Read the menu items directly from this script file.</em>
    f_FavoritesFile := A_ScriptFullPath

<em>;----Read the configuration file.</em>
f_AtStartingPos := false
f_MenuItemCount := 0
f_Paths := []
f_Menu := MenuCreate()
Loop Read, f_FavoritesFile
{
    if f_FileExt != "Exe"
    {
        <em>; Since the menu items are being read directly from this
        ; script, skip over all lines until the starting line is
        ; arrived at.</em>
        if !f_AtStartingPos
        {
            if InStr(A_LoopReadLine, "ITEMS IN FAVORITES MENU")
                f_AtStartingPos := true
            continue  <em>; Start a new loop iteration.</em>
        }
        <em>; Otherwise, the closing comment symbol marks the end of the list.</em>
        if A_LoopReadLine = "*/"
            break  <em>; terminate the loop</em>
    }
    <em>; Menu separator lines must also be counted to be compatible
    ; with ItemPos:</em>
    f_MenuItemCount++
    if !A_LoopReadLine  <em>; Blank indicates a separator line.</em>
        f_Menu.Add()
    else
    {
        f_line := StrSplit(A_LoopReadLine, ";", "`s`t")
        <em>; Resolve any references to variables within either field, and
        ; create a new array element containing the path of this favorite:</em>
        f_Paths[f_MenuItemCount] := f_line[2]
        f_Menu.Add(f_line[1], "f_OpenFavorite")
    }
}
return  <em>;----End of auto-execute section.


;----Open the selected favorite</em>
f_OpenFavorite(ItemName, ItemPos, *)
{
    global
    
    <em>; Fetch the array element that corresponds to the selected menu item:</em>
    f_path := f_Paths[ItemPos]
    if f_path = ""
        return
    if f_class = "#32770"    <em>; It's a dialog.</em>
    {
        <em>; Activate the window so that if the user is middle-clicking
        ; outside the dialog, subsequent clicks will also work:</em>
        WinActivate "ahk_id " f_window_id
        <em>; Retrieve any filename that might already be in the field so
        ; that it can be restored after the switch to the new folder:</em>
        f_text := ControlGetText("Edit1", "ahk_id " f_window_id)
        ControlSetText f_path, "Edit1", "ahk_id " f_window_id
        ControlFocus "Edit1", "ahk_id " f_window_id
        ControlSend "{Enter}", "Edit1", "ahk_id " f_window_id
        Sleep 100  <em>; It needs extra time on some dialogs or in some cases.</em>
        ControlSetText f_text, "Edit1", "ahk_id " f_window_id
        return
    }
    else if f_class  = "CabinetWClass"  <em>; In Explorer, switch folders.</em>
    {
        ControlClick "ToolbarWindow323", "ahk_id " f_window_id,,,, "NA x1 y1"
        ControlFocus "Edit1", "ahk_id " f_window_id
        ControlSetText f_path, "Edit1", "ahk_id " f_window_id
        <em>; Tekl reported the following: "If I want to change to Folder L:\folder
        ; then the addressbar shows http://www.L:\folder.com. To solve this,
        ; I added a {right} before {Enter}":</em>
        ControlSend "{Right}{Enter}", "Edit1", "ahk_id " f_window_id
        return
    }
    else if f_class = "ConsoleWindowClass" <em>; In a console window, CD to that directory</em>
    {
        WinActivate "ahk_id " f_window_id <em>; Because sometimes the mclick deactivates it.</em>
        SetKeyDelay 0  <em>; This will be in effect only for the duration of this thread.</em>
        if InStr(f_path, ":")  <em>; It contains a drive letter</em>
        {
            f_path_drive := SubStr(f_path, 1, 1)
            Send f_path_drive ":{enter}"
        }
        Send "cd " f_path "{Enter}"
        return
    }
    <em>; Since the above didn't return, one of the following is true:
    ; 1) It's an unsupported window type but f_AlwaysShowMenu is y (yes).</em>
    Run "explorer " f_path  <em>; Might work on more systems without double quotes.</em>
}


<em>;----Display the menu</em>
f_DisplayMenu:
<em>; These first few variables are set here and used by f_OpenFavorite:</em>
f_window_id := WinGetID("A")
f_class := WinGetClass("ahk_id " f_window_id)
if f_AlwaysShowMenu = false  <em>; The menu should be shown only selectively.</em>
{
    if !(f_class ~= "#32770|ExploreWClass|CabinetWClass|ConsoleWindowClass")
        return <em>; Since it's some other window type, don't display menu.</em>
}
<em>; Otherwise, the menu should be presented for this type of window:</em>
f_Menu.Show()
return
</pre>
</body>
</html>